#ifndef _EXPRESSION_H_
#define _EXPRESSION_H_

#include <regex>

#include "types.h"

enum class TokenType {
    ADD, SUB, MUL, DIV, 
    NUM, REG, 
    LPAR, RPAR,
    EQ, NEQ, GT, LT,
    AND, OR, NOT, NEG,
    SPACE,
};

struct Rule {
    std::regex regex;
    TokenType type;
};

struct Token {
    TokenType type;
    std::string value;
};

class Expression {
private:
    int cur_idx;
    std::vector<Token> tokens;
    bool make_token(const char* expr);
    std::function<word_t(std::string&, bool& success)> get_reg_val;

    /**
    * expr       := logic_or
    * logic_or   := logic_and ("||" and) *
    * logic_and  := eq_neq ("&&" eq_neq) *
    * eq_neq     := gt_lt ("==" gt_lt | "!=" gt_lt)*
    * gt_lt      := add_sub ("<" add_sub | ">" add_sub)*
    * add_sub    := mul_div ("+" mul_div | "-" mul_div)*
    * mul_div    := unary ("*" unary | "/" unary)*
    * unary      := ("+" | "-" | "!" | "*")? primary
    * primary    := num | "(" expr ")"
    */
    word_t parse_expr(bool& success);
    word_t parse_logic_or(bool& success);
    word_t parse_logic_and(bool& success);
    word_t parse_eq_neq(bool& success);
    word_t parse_gt_lt(bool& success);
    word_t parse_add_sub(bool& success);
    word_t parse_mul_div(bool& success);
    word_t parse_unary(bool& success);
    word_t parse_primary(bool& success);

public:
    std::tuple<bool, word_t> parser(const char* expr);
    Expression(std::function<word_t(std::string&, bool& success)> get_reg_val) : get_reg_val(get_reg_val) {}
    Expression() = default;
    ~Expression() = default;
};

#endif
